package com.yc.thread;

public class TestThreadLocal2 {
	
	/**
	 * get | set | remove
	 */
	public void m() {
//		ThreadLocal<int> t1 = new ThreadLocal<int>();// wrong
		ThreadLocal<String> t1 = new ThreadLocal<String>();
		ThreadLocal<Integer> t2 = new ThreadLocal<Integer>();
		ThreadLocal<Entity> t3 = new ThreadLocal<Entity>();
		
		t1.set("aaa");
		t1.set("bbb");//一个ThreadLocal的数据结构只能存一个对象，获取的方式也是简单的get
		t2.set(2);
		t3.set(new Entity("ccc"));
		
		System.out.println(t1.get());
		System.out.println(t2.get());
		System.out.println(t3.get());
		
		t1.remove();
		t2.remove();
		t3.remove();
		
		System.out.println(t1.get());
		System.out.println(t2.get());
		System.out.println(t3.get());
	}
	
	/**
	 * 各个线程，各玩各的，包括main线程的值互不影响
	 */
	public void m1() {
		//继承父类的[匿名内部类]
		ThreadLocal<Integer> a = new ThreadLocal<Integer>() {
			@Override
			protected Integer initialValue() {
				return 0;
			}
		};
		
		//如果想创建时 初始化的写法
//		ThreadLocal<Integer> a = ThreadLocal.withInitial(() -> {
//			return 0;
//		});
		
		//lamdba表达式本质上是 实现接口的[匿名内部类]
		Runnable cc = new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				
			}
		};
		
		Thread t1 = new Thread(() -> {
			for (int i = 0; i < 10; i++) {
				a.set(a.get()+1);
			}
		});
		
		Thread t2 = new Thread(() -> {
			for (int i = 0; i < 10; i++) {
				a.set(a.get()+1);
			}
		});
		
		t1.start();
		t2.start();
		
		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(a.get());
		
	}
	
	public void m2() {
		  String a = "aaaa";
		  ThreadLocal<String> ttThreadLocal = ThreadLocal.withInitial(()->a);
		  Thread t1 = new Thread(()->{
			  ttThreadLocal.set("ccc");
		  });
		  t1.start();
		  try {
		    t1.join();
		    System.out.println(a);
		  } catch (Exception e) {
		    e.printStackTrace();
		  }
	}
	
	/*
	 * 两个线程获取到的对象不同
	 * 	com.yc.thread.TestThreadLocal2$Entity@1f453e73
		com.yc.thread.TestThreadLocal2$Entity@5fe83edb
	 */
	public void m3() {
		ThreadLocal<Entity> t = ThreadLocal.withInitial(() -> {
			return new Entity("xy");
		});
		
		Thread td = new Thread(() -> {
			System.out.println(t.get());
		});
		td.start();
		Thread td2 = new Thread(() -> {
			System.out.println(t.get());
		});
		td2.start();
		try {
			td.join();
			td2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 	两个线程获取到的对象是同一个
	 * 	com.yc.thread.TestThreadLocal2$Entity@60fc096
		com.yc.thread.TestThreadLocal2$Entity@60fc096
	 */
	public void m3_1() {
		Entity entity = new Entity("xy");
		ThreadLocal<Entity> t = ThreadLocal.withInitial(() -> {
			return entity;
		});
		
		Thread td = new Thread(() -> {
			System.out.println(t.get());
		});
		td.start();
		Thread td2 = new Thread(() -> {
			System.out.println(t.get());
		});
		td2.start();
		try {
			td.join();
			td2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 结果：td线程没有改变主线程里ThreadLocal的值
		main: xy
	 */
	public void m4() {
		ThreadLocal<Entity> t = ThreadLocal.withInitial(() -> {
			return new Entity("xy");
		});
		
		Thread td = new Thread(() -> {
			t.get().a = "xy----td";//试图改变main线程的值
		});
		td.start();
		try {
			td.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("main: " + t.get().a);
		
	}
	
	/**
	 * 结果：td线程改变了主线程里ThreadLocal的值
	 * 		main: xy----td
	 */
	public void m5() {
		Entity entity = new Entity("xy");
		ThreadLocal<Entity> t = ThreadLocal.withInitial(() -> {
			return entity;
		});
		
		Thread td = new Thread(() -> {
			t.get().a = "xy----td";//试图改变main线程的值
		});
		td.start();
		try {
			td.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("main: " + t.get().a);
		
	}

	public static void main(String[] args) {
		TestThreadLocal2 tt = new TestThreadLocal2();
//		tt.m();
//		tt.m1();
//		tt.m2();
		tt.m3();
//		tt.m3_1();
//		tt.m4();
//		tt.m5();

	}
	
	class Entity {
		String a;

		public Entity(String a) {
			super();
			this.a = a;
		}
		
	}

}
